1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "file_utils.h"
17
18 #include <fcntl.h>
19 #include <sys/sendfile.h>
20 #include <sys/stat.h>
21
22 #include "media_log.h"
23 #include "media_file_utils.h"
24 #include "database_adapter.h"
25 #include "result_set_utils.h"
26 #include "media_column.h"
27 #include "image_packer.h"
28 #include "medialibrary_errno.h"
29 #include "medialibrary_tracer.h"
30 #include "medialibrary_type_const.h"
31 #include "medialibrary_operation.h"
32 #include "medialibrary_object_utils.h"
33 #include "picture.h"
34 #include "image_type.h"
35
36 using namespace std;
37
38 namespace OHOS {
39 namespace Media {
40 const std::string MIME_TYPE_HEIF = "image/heif";
41 const std::string MIME_TYPE_HEIC = "image/heic";
FileUtils()42 FileUtils::FileUtils() {}
43
~FileUtils()44 FileUtils::~FileUtils() {}
45
DeleteFile(const string & fileName)46 int FileUtils::DeleteFile(const string &fileName)
47 {
48 int ret = remove(fileName.c_str());
49 if (ret < 0) {
50 MEDIA_ERR_LOG("DeleteFile fail, ret: %{public}d, errno: %{public}d", ret, errno);
51 }
52 return ret;
53 }
54
IsFileExist(const string & fileName)55 bool FileUtils::IsFileExist(const string &fileName)
56 {
57 struct stat statInfo {};
58 return ((stat(fileName.c_str(), &statInfo)) == E_SUCCESS);
59 }
60
SaveImage(const string & filePath,void * output,size_t writeSize)61 int32_t FileUtils::SaveImage(const string &filePath, void *output, size_t writeSize)
62 {
63 const mode_t fileMode = 0644;
64 MediaLibraryTracer tracer;
65 tracer.Start("FileUtils::SaveImage");
66 string filePathTemp = filePath + ".high";
67 int fd = open(filePathTemp.c_str(), O_CREAT|O_WRONLY|O_TRUNC, fileMode);
68 if (fd < 0) {
69 MEDIA_ERR_LOG("fd.Get() < 0 fd %{public}d errno: %{public}d", fd, errno);
70 return E_ERR;
71 }
72 MEDIA_DEBUG_LOG("filePath: %{private}s, fd: %{public}d", filePath.c_str(), fd);
73
74 int ret = write(fd, output, writeSize);
75 close(fd);
76 if (ret < 0) {
77 MEDIA_ERR_LOG("write fail, ret: %{public}d, errno: %{public}d", ret, errno);
78 DeleteFile(filePathTemp);
79 return ret;
80 }
81
82 ret = rename(filePathTemp.c_str(), filePath.c_str());
83 if (ret < 0) {
84 MEDIA_ERR_LOG("rename fail, ret: %{public}d, errno: %{public}d", ret, errno);
85 DeleteFile(filePathTemp);
86 return ret;
87 }
88
89 return ret;
90 }
91
SavePicture(const string & imageId,std::shared_ptr<Media::Picture> & picture,bool isEdited,bool isLowQualityPicture)92 int32_t FileUtils::SavePicture(const string &imageId, std::shared_ptr<Media::Picture> &picture,
93 bool isEdited, bool isLowQualityPicture)
94 {
95 MediaLibraryTracer tracer;
96 // 通过imageid获取fileid 获取uri
97 if (picture == nullptr) {
98 return -1;
99 }
100 MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
101 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
102 string where = PhotoColumn::PHOTO_ID + " = ? ";
103 vector<string> whereArgs { imageId };
104 cmd.GetAbsRdbPredicates()->SetWhereClause(where);
105 cmd.GetAbsRdbPredicates()->SetWhereArgs(whereArgs);
106 vector<string> columns { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH, PhotoColumn::PHOTO_EDIT_TIME,
107 PhotoColumn::PHOTO_SUBTYPE, MediaColumn::MEDIA_MIME_TYPE};
108 tracer.Start("Query");
109 auto resultSet = DatabaseAdapter::Query(cmd, columns);
110 if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
111 tracer.Finish();
112 MEDIA_INFO_LOG("result set is empty");
113 return -1;
114 }
115 tracer.Finish();
116 string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
117 int fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
118 string sourcePath = isEdited ? MediaLibraryAssetOperations::GetEditDataSourcePath(path) : path;
119 //查询是否编辑 编辑目录下
120 string mime_type = GetStringVal(MediaColumn::MEDIA_MIME_TYPE, resultSet);
121 resultSet->Close();
122 if (mime_type == "") {
123 mime_type = "image/jpeg";
124 }
125 size_t sizeHeic = -1;
126 size_t pos = sourcePath.find_last_of('.');
127 string pathPos = sourcePath.substr(0, pos);
128 string pathHeic = pathPos + ".heic";
129 MediaFileUtils::GetFileSize(pathHeic, sizeHeic);
130 size_t sizeJpeg = -1;
131 string pathJpeg = pathPos + ".jpeg";
132 MediaFileUtils::GetFileSize(pathJpeg, sizeJpeg);
133
134 if (isLowQualityPicture && (sizeHeic > 0 || sizeJpeg > 0)) {
135 return -1;
136 }
137
138 int ret = DealPicture(mime_type, sourcePath, picture, !isLowQualityPicture);
139 return ret;
140 }
141
SavePicture(const string & path,std::shared_ptr<Media::Picture> & picture,const std::string & mime_type,bool isHighQualityPicture)142 int32_t FileUtils::SavePicture(const string &path, std::shared_ptr<Media::Picture> &picture,
143 const std::string &mime_type, bool isHighQualityPicture)
144 {
145 MEDIA_INFO_LOG("SavePicture width %{public}d, heigh %{public}d, mime_type %{public}sd",
146 picture->GetMainPixel()->GetWidth(), picture->GetMainPixel()->GetHeight(), mime_type.c_str());
147 return DealPicture(mime_type, path, picture, isHighQualityPicture);
148 }
149
DealPicture(const std::string & mime_type,const std::string & path,std::shared_ptr<Media::Picture> & picture,bool isHighQualityPicture)150 int32_t FileUtils::DealPicture(const std::string &mime_type, const std::string &path,
151 std::shared_ptr<Media::Picture> &picture, bool isHighQualityPicture)
152 {
153 MEDIA_DEBUG_LOG("DealPicture %{public}s", path.c_str());
154 if (picture == nullptr) {
155 return -1;
156 }
157 Media::ImagePacker imagePacker;
158 Media::PackOption packOption;
159 packOption.format = (mime_type == MIME_TYPE_HEIC) ? MIME_TYPE_HEIF : mime_type;
160 packOption.needsPackProperties = true;
161 packOption.desiredDynamicRange = EncodeDynamicRange::AUTO;
162 packOption.isEditScene = false;
163 size_t lastSlash = path.rfind('/');
164 CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && path.size() > (lastSlash + 1), E_INVALID_VALUES,
165 "Failed to check outputPath: %{public}s", path.c_str());
166 string tempInternal = isHighQualityPicture ? "high_" :"low_";
167 string tempOutputPath = path.substr(0, lastSlash) + tempInternal + path.substr(lastSlash + 1);
168 int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
169 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_FS_ERROR,
170 "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
171 imagePacker.StartPacking(tempOutputPath, packOption);
172 imagePacker.AddPicture(*(picture));
173 imagePacker.FinalizePacking();
174 size_t size = -1;
175 MediaFileUtils::GetFileSize(tempOutputPath, size);
176 MEDIA_DEBUG_LOG("SavePicture end {public}%zu", size);
177 if (size == 0) {
178 CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
179 "Failed to delete temp filters file, errno: %{public}d", errno);
180 return E_OK;
181 }
182 ret = rename(tempOutputPath.c_str(), path.c_str());
183 if (MediaFileUtils::IsFileExists(tempOutputPath)) {
184 MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", tempOutputPath.c_str());
185 if (!MediaFileUtils::DeleteFile(tempOutputPath)) {
186 MEDIA_ERR_LOG("delete file: %{public}s failed", tempOutputPath.c_str());
187 }
188 }
189 return ret;
190 }
191
SaveVideo(const std::string & filePath,bool isEdited)192 int32_t FileUtils::SaveVideo(const std::string &filePath, bool isEdited)
193 {
194 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
195 string targetPath = filePath;
196 if (isEdited) {
197 targetPath = MediaLibraryAssetOperations::GetEditDataSourcePath(filePath);
198 }
199
200 if (!IsFileExist(filePath)) {
201 MEDIA_INFO_LOG("file not exist: %{public}s", filePath.c_str());
202 }
203
204 if (!IsFileExist(tempPath)) {
205 MEDIA_INFO_LOG("file not exist: %{public}s", tempPath.c_str());
206 }
207
208 MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s", targetPath.c_str(), tempPath.c_str());
209 return rename(tempPath.c_str(), targetPath.c_str());
210 }
211
DeleteTempVideoFile(const std::string & filePath)212 int32_t FileUtils::DeleteTempVideoFile(const std::string &filePath)
213 {
214 MEDIA_INFO_LOG("filePath: %{public}s", filePath.c_str());
215 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
216 if (IsFileExist(tempPath)) {
217 return DeleteFile(tempPath);
218 }
219 return E_OK;
220 }
221 } // namespace Media
222 } // namespace OHOS