• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2024 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 #include <sstream>
16 
17 #include "media_file_utils.h"
18 #include "media_log.h"
19 #include "medialibrary_errno.h"
20 #include "media_file_uri.h"
21 #include "medialibrary_helper_container.h"
22 #include "medialibrary_type_const.h"
23 #include "photo_album_column.h"
24 #include "string_ex.h"
25 #include "userfilemgr_uri.h"
26 #include "media_column.h"
27 #include "medialibrary_db_const.h"
28 
29 using namespace std;
30 namespace OHOS {
31 namespace Media {
32 const size_t LEAST_PATH_LENGTH = 2;
33 const size_t BATCH_SIZE_START_AND_END = 2;
34 const std::string MEDIA_FILE_ID_DEFAULT = "-1";
35 
36 const int ASSET_IN_BUCKET_NUM_MAX = 1000;
37 const int ASSET_DIR_START_NUM = 16;
38 const int ASSET_MAX_NUM = 10000000;
39 
SolveMediaTypeV9(MediaType mediaType)40 static std::string SolveMediaTypeV9(MediaType mediaType)
41 {
42     switch (mediaType) {
43         case MEDIA_TYPE_AUDIO:
44             return MEDIALIBRARY_TYPE_AUDIO_URI;
45         case MEDIA_TYPE_VIDEO:
46             return MEDIALIBRARY_TYPE_VIDEO_URI;
47         case MEDIA_TYPE_IMAGE:
48             return MEDIALIBRARY_TYPE_IMAGE_URI;
49         case MEDIA_TYPE_FILE:
50         default:
51             return MEDIALIBRARY_TYPE_FILE_URI;
52     }
53 }
54 
SolveMediaTypeV10(MediaType mediaType)55 static std::string SolveMediaTypeV10(MediaType mediaType)
56 {
57     switch (mediaType) {
58         case MEDIA_TYPE_AUDIO:
59             return AudioColumn::AUDIO_TYPE_URI;
60         case MEDIA_TYPE_VIDEO:
61         case MEDIA_TYPE_IMAGE:
62             return PhotoColumn::PHOTO_TYPE_URI;
63         case MEDIA_TYPE_FILE:
64         default:
65             return MEDIALIBRARY_TYPE_FILE_URI;
66     }
67 }
68 
SolveMediaType(MediaType mediaType)69 static std::string SolveMediaType(MediaType mediaType)
70 {
71     switch (mediaType) {
72         case MEDIA_TYPE_AUDIO:
73             return MEDIALIBRARY_TYPE_AUDIO_URI;
74         case MEDIA_TYPE_VIDEO:
75             return MEDIALIBRARY_TYPE_VIDEO_URI;
76         case MEDIA_TYPE_IMAGE:
77             return MEDIALIBRARY_TYPE_IMAGE_URI;
78         case MEDIA_TYPE_ALBUM:
79             return MEDIALIBRARY_TYPE_ALBUM_URI;
80         case MEDIA_TYPE_SMARTALBUM:
81             return MEDIALIBRARY_TYPE_SMART_URI;
82         case MEDIA_TYPE_FILE:
83         default:
84             return MEDIALIBRARY_TYPE_FILE_URI;
85     }
86 }
87 
ParseUri(const string & uri)88 void MediaFileUri::ParseUri(const string &uri)
89 {
90     if (MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
91         uriType_ = API10_PHOTO_URI;
92     } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ALBUM_URI_PREFIX)) {
93         uriType_ = API10_PHOTOALBUM_URI;
94     } else if (MediaFileUtils::StartsWith(uri, AudioColumn::AUDIO_URI_PREFIX)) {
95         uriType_ = API10_AUDIO_URI;
96     } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX)) {
97         uriType_ = API10_ANALYSISALBUM_URI;
98     } else  {
99         uriType_ = API9_URI;
100     }
101 }
102 
GetMediaTypeUri(MediaType mediaType,const int32_t & apiVersion)103 std::string MediaFileUri::GetMediaTypeUri(MediaType mediaType, const int32_t &apiVersion)
104 {
105     switch (apiVersion) {
106         case MEDIA_API_VERSION_V9:
107             return SolveMediaTypeV9(mediaType);
108         case MEDIA_API_VERSION_V10:
109             return SolveMediaTypeV10(mediaType);
110         case MEDIA_API_VERSION_DEFAULT:
111         default:
112             return SolveMediaType(mediaType);
113     }
114 }
115 
MediaFileUriConstruct(MediaType mediaType,const std::string & fileId,const std::string & networkId,const int32_t & apiVersion,const std::string & extrUri)116 std::string MediaFileUri::MediaFileUriConstruct(MediaType mediaType, const std::string &fileId,
117     const std::string &networkId, const int32_t &apiVersion, const std::string &extrUri)
118 {
119     std::string uri = ML_FILE_URI_PREFIX;
120     uri += GetMediaTypeUri(mediaType, apiVersion);
121     if (!fileId.empty()) {
122         uri += "/" + fileId;
123     }
124 
125     if (!networkId.empty()) {
126         uri += ML_URI_NETWORKID_EQUAL + networkId;
127     }
128 
129     if (apiVersion == MEDIA_API_VERSION_V10) {
130         uri += extrUri;
131         uri = MediaFileUtils::Encode(uri);
132     }
133     ParseUri(uri);
134     return uri;
135 }
136 
SetQueryMap(MediaFileUri * uri,std::unordered_map<std::string,std::string> & queryMap)137 static void SetQueryMap(MediaFileUri* uri, std::unordered_map<std::string,
138     std::string> &queryMap)
139 {
140     // file://media/image/12?networkid=xxxx&api_version=xxxx
141     std::string query = uri->GetQuery();
142     std::string pairString;
143     std::stringstream queryStream(query);
144 
145     while (getline(queryStream, pairString, '&')) {
146         size_t splitIndex = pairString.find('=');
147         if (splitIndex == std::string::npos || splitIndex == (pairString.length() - 1)) {
148             MEDIA_ERR_LOG("failed to parse query, query field is %{private}s!", pairString.c_str());
149             continue;
150         }
151         queryMap[pairString.substr(0, splitIndex)] = pairString.substr(splitIndex + 1);
152     }
153     return;
154 }
155 
CalNetworkId(MediaFileUri * uri,std::unordered_map<std::string,std::string> queryMap)156 static std::string CalNetworkId(MediaFileUri* uri, std::unordered_map<std::string,
157     std::string> queryMap)
158 {
159     std::string scheme = uri->GetScheme();
160     if (scheme == ML_FILE_SCHEME) {
161         if (queryMap.find(ML_URI_NETWORKID) != queryMap.end()) {
162             return queryMap[ML_URI_NETWORKID];
163         }
164         return "";
165     } else if (scheme == ML_DATA_SHARE_SCHEME) {
166         return uri->GetAuthority();
167     }
168     MEDIA_DEBUG_LOG("CalNetworkId scheme is invalid, scheme is %{private}s", scheme.c_str());
169     return "";
170 }
171 
GetNetworkId()172 const std::string& MediaFileUri::GetNetworkId()
173 {
174     if (this->networkId_ != MEDIA_FILE_URI_EMPTY) {
175         return this->networkId_;
176     }
177     SetQueryMap(this, this->queryMap_);
178     this->networkId_ = CalNetworkId(this, this->queryMap_);
179     return this->networkId_;
180 }
181 
ParsePathWithExtrPara(std::string & path)182 static void ParsePathWithExtrPara(std::string &path)
183 {
184     auto index = path.rfind('/');
185     if (index == std::string::npos) {
186         MEDIA_ERR_LOG("find split for last string failed, %{private}s", path.c_str());
187         return;
188     }
189     auto lastStr = path.substr(index + 1);
190     auto uriTempNext = path.substr(0, index);
191     index = uriTempNext.rfind('/');
192     if (index == std::string::npos) {
193         MEDIA_ERR_LOG("find split for next string failed %{private}s", uriTempNext.c_str());
194         return;
195     }
196     auto preStr = uriTempNext.substr(index + 1);
197     if (lastStr.find('.') != std::string::npos) {
198         if (!all_of(preStr.begin(), preStr.end(), ::isdigit)) {
199             path = uriTempNext.substr(0, index);
200             return;
201         }
202         preStr = uriTempNext.substr(0, index);
203         index = preStr.rfind('/');
204         if (index == std::string::npos) {
205             path = uriTempNext;
206             return;
207         }
208         path = preStr;
209     }
210 }
211 
CalFileId(MediaFileUri * uri)212 static std::string CalFileId(MediaFileUri* uri)
213 {
214     std::string path = uri->GetPath();
215     if (uri->IsApi10()) {
216         ParsePathWithExtrPara(path);
217     }
218 
219     if (path.length() < LEAST_PATH_LENGTH) {
220         MEDIA_ERR_LOG("path is too short, path is %{private}s", path.c_str());
221         return MEDIA_FILE_ID_DEFAULT;
222     }
223 
224     std::size_t index = path.rfind("/");
225     if (index == std::string::npos || index == path.length() - 1) {
226         MEDIA_ERR_LOG("failed to rfind /, path is %{private}s", path.c_str());
227         return MEDIA_FILE_ID_DEFAULT;
228     }
229 
230     std::string fileId = path.substr(index + 1);
231     if (!std::all_of(fileId.begin(), fileId.end(), ::isdigit)) {
232         MEDIA_DEBUG_LOG("fileId is not all digit, fileId is %{private}s", fileId.c_str());
233         return MEDIA_FILE_ID_DEFAULT;
234     }
235 
236     return fileId;
237 }
238 
GetFileId()239 std::string MediaFileUri::GetFileId()
240 {
241     if (this->fileId_ != MEDIA_FILE_URI_EMPTY) {
242         return this->fileId_;
243     }
244     this->fileId_ = CalFileId(this);
245     return this->fileId_;
246 }
247 
GetTableName()248 std::string MediaFileUri::GetTableName()
249 {
250     static std::map<std::string, std::string> tableNameMap = {
251         { MEDIALIBRARY_TYPE_IMAGE_URI, PhotoColumn::PHOTOS_TABLE },
252         { MEDIALIBRARY_TYPE_VIDEO_URI, PhotoColumn::PHOTOS_TABLE },
253         { MEDIALIBRARY_TYPE_AUDIO_URI, AudioColumn::AUDIOS_TABLE },
254         { MEDIALIBRARY_TYPE_FILE_URI, MEDIALIBRARY_TABLE },
255         { AudioColumn::AUDIO_TYPE_URI, AudioColumn::AUDIOS_TABLE },
256         { PhotoColumn::PHOTO_TYPE_URI, PhotoColumn::PHOTOS_TABLE }
257     };
258 
259     std::string uriString = ToString();
260     size_t questionPosition = uriString.find_first_of('?');
261     if (questionPosition != string::npos) {
262         uriString = uriString.substr(0, questionPosition);
263     }
264 
265     for (const auto &iter : tableNameMap) {
266         if (uriString.find(iter.first) != std::string::npos) {
267             return iter.second;
268         }
269     }
270     return "";
271 }
272 
GetFilePath()273 std::string MediaFileUri::GetFilePath()
274 {
275     /* get helper */
276     std::shared_ptr<DataShare::DataShareHelper> dataShareHelper =
277             MediaLibraryHelperContainer::GetInstance()->GetDataShareHelper();
278     if (dataShareHelper == nullptr) {
279         MEDIA_ERR_LOG("get data share helper err");
280         return "";
281     }
282 
283     DataShare::DatashareBusinessError error;
284     const std::string uriString = ToString();
285     std::string queryUri(UFM_QUERY_PHOTO);
286     DataShare::DataSharePredicates predicates;
287     std::vector<std::string> columns;
288     /* check api version */
289     if (uriString.find(PhotoColumn::PHOTO_TYPE_URI) != std::string::npos) {
290         predicates.EqualTo(MediaColumn::MEDIA_ID, GetFileId());
291         columns.emplace_back(MediaColumn::MEDIA_FILE_PATH);
292         MediaFileUtils::UriAppendKeyValue(queryUri, URI_PARAM_API_VERSION);
293     } else {
294         predicates.EqualTo(MEDIA_DATA_DB_ID, GetFileId());
295         columns.emplace_back(MEDIA_DATA_DB_FILE_PATH);
296     }
297     Uri uri(queryUri);
298     /* query and check */
299     auto resultSet = dataShareHelper->Query(uri, predicates, columns, &error);
300     int32_t ret = error.GetCode();
301     if (ret != 0) {
302         MEDIA_ERR_LOG("data share query err %{public}d", ret);
303         return "";
304     }
305     int32_t rowCount;
306     ret = resultSet->GetRowCount(rowCount);
307     if (ret != 0) {
308         MEDIA_ERR_LOG("result set get row count err %{public}d", ret);
309         return "";
310     }
311     if (rowCount != 1) {
312         MEDIA_ERR_LOG("more than one record");
313         return "";
314     }
315 
316     /* get val */
317     ret = resultSet->GoToNextRow();
318     if (ret != 0) {
319         MEDIA_ERR_LOG("result set go to next row err %{public}d", ret);
320         return "";
321     }
322     std::string val;
323     ret = resultSet->GetString(0, val);
324     if (ret != 0) {
325         MEDIA_ERR_LOG("result set get string err %{public}d", ret);
326         return "";
327     }
328     return val;
329 }
330 
IsValid()331 bool MediaFileUri::IsValid()
332 {
333     std::string scheme = this->GetScheme();
334     if (scheme != ML_FILE_SCHEME &&
335         scheme != ML_DATA_SHARE_SCHEME) {
336         MEDIA_ERR_LOG("scheme is invalid, uri is %{private}s", this->ToString().c_str());
337         return false;
338     }
339 
340     if (this->GetAuthority() != ML_URI_AUTHORITY &&
341         this->GetPath().find(MEDIALIBRARY_DATA_URI_IDENTIFIER) != 0) {
342         MEDIA_ERR_LOG("failed to find /media, uri is %{private}s", this->ToString().c_str());
343         return false;
344     }
345 
346     std::string fileId = this->GetFileId();
347     if (fileId == MEDIA_FILE_ID_DEFAULT) {
348         MEDIA_ERR_LOG("fileid is invaild, uri is %{private}s", this->ToString().c_str());
349         return false;
350     }
351 
352     return true;
353 }
354 
GetQueryKeys()355 std::unordered_map<std::string, std::string> &MediaFileUri::GetQueryKeys()
356 {
357     if (queryMap_.empty()) {
358         SetQueryMap(this, this->queryMap_);
359     }
360     return queryMap_;
361 }
362 
IsApi10()363 bool MediaFileUri::IsApi10()
364 {
365     if ((ToString().find(PhotoColumn::PHOTO_TYPE_URI) != std::string::npos) ||
366         (ToString().find(AudioColumn::AUDIO_TYPE_URI) != std::string::npos) ||
367         (ToString().find(PhotoColumn::HIGHTLIGHT_COVER_URI) != std::string::npos)) {
368         return true;
369     }
370     return false;
371 }
372 
GetUriType()373 int MediaFileUri::GetUriType()
374 {
375     return uriType_;
376 }
377 
GetMediaTypeFromUri(const std::string & uri)378 MediaType MediaFileUri::GetMediaTypeFromUri(const std::string &uri)
379 {
380     if (MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
381         return MEDIA_TYPE_PHOTO;
382     } else if (MediaFileUtils::StartsWith(uri, AudioColumn::AUDIO_URI_PREFIX)) {
383         return MEDIA_TYPE_AUDIO;
384     } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ALBUM_URI_PREFIX)) {
385         return Media::MEDIA_TYPE_ALBUM;
386     } else if (MediaFileUtils::StartsWith(uri, AUDIO_URI_PREFIX)) {
387         return Media::MEDIA_TYPE_AUDIO;
388     } else if (MediaFileUtils::StartsWith(uri, VIDEO_URI_PREFIX)) {
389         return Media::MEDIA_TYPE_VIDEO;
390     } else if (MediaFileUtils::StartsWith(uri, IMAGE_URI_PREFIX)) {
391         return Media::MEDIA_TYPE_IMAGE;
392     } else if (MediaFileUtils::StartsWith(uri, ALBUM_URI_PREFIX)) {
393         return Media::MEDIA_TYPE_ALBUM;
394     } else if (MediaFileUtils::StartsWith(uri, FILE_URI_PREFIX)) {
395         return Media::MEDIA_TYPE_FILE;
396     } else if (MediaFileUtils::StartsWith(uri, HIGHLIGHT_URI_PREFIX)) {
397         return Media::MEDIA_TYPE_FILE;
398     }
399     return Media::MEDIA_TYPE_DEFAULT;
400 }
401 
RemoveAllFragment(std::string & uri)402 void MediaFileUri::RemoveAllFragment(std::string &uri)
403 {
404     size_t fragIndex = uri.find_first_of('#');
405     if (fragIndex != std::string::npos) {
406         uri = uri.substr(0, fragIndex);
407     }
408 }
409 
UriValidCheck(Uri & uri)410 static int32_t UriValidCheck(Uri &uri)
411 {
412     std::string scheme = uri.GetScheme();
413     if (scheme != ML_FILE_SCHEME && scheme != ML_DATA_SHARE_SCHEME) {
414         MEDIA_ERR_LOG("scheme is invalid, uri is %{private}s", uri.ToString().c_str());
415         return E_INVALID_URI;
416     }
417 
418     if (uri.GetAuthority() != ML_URI_AUTHORITY && uri.GetPath().find(MEDIALIBRARY_DATA_URI_IDENTIFIER) != 0) {
419         MEDIA_ERR_LOG("failed to find /media, uri is %{private}s", uri.ToString().c_str());
420         return E_INVALID_URI;
421     }
422     return E_OK;
423 }
424 
HandleOldUriPath(std::string & path)425 static inline void HandleOldUriPath(std::string &path)
426 {
427     // Handle datashare:///media and datashare:///media/file_operation case
428     if (MediaFileUtils::StartsWith(path, MEDIALIBRARY_DATA_URI_IDENTIFIER)) {
429         path = path.substr(MEDIALIBRARY_DATA_URI_IDENTIFIER.size());
430         return;
431     }
432 }
433 
RemovePrecedSlash(std::string & path)434 static inline void RemovePrecedSlash(std::string &path)
435 {
436     if (MediaFileUtils::StartsWith(path, SLASH_STR)) {
437         path = path.substr(SLASH_STR.size());
438     }
439 }
440 
GetValidPath(Uri & uri,std::string & path)441 static void GetValidPath(Uri &uri, std::string &path)
442 {
443     if (UriValidCheck(uri) < 0) {
444         path = "";
445         return;
446     }
447 
448     path = uri.GetPath();
449     HandleOldUriPath(path);
450     RemovePrecedSlash(path);
451 }
452 
GetPathFirstDentry(Uri & uri)453 std::string MediaFileUri::GetPathFirstDentry(Uri &uri)
454 {
455     std::string path;
456     GetValidPath(uri, path);
457     // Example: file:://media/photo_operation/query, return the "photo_operation" part
458     return path.substr(0, path.find_first_of('/'));
459 }
460 
GetPathSecondDentry(Uri & uri)461 std::string MediaFileUri::GetPathSecondDentry(Uri &uri)
462 {
463     std::string ret;
464     std::string firstDentry = GetPathFirstDentry(uri);
465     if (firstDentry.empty()) {
466         return ret;
467     }
468     std::string path;
469     GetValidPath(uri, path);
470     if (path.size() < firstDentry.size() + 1) {
471         return ret;
472     }
473     // Example: file:://media/photo_operation/query, return the "query" part
474     return path.substr(firstDentry.size() + 1);
475 }
476 
GetPhotoId(const std::string & uri)477 std::string MediaFileUri::GetPhotoId(const std::string &uri)
478 {
479     if (!MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
480         return "";
481     }
482     std::string tmp = uri.substr(PhotoColumn::PHOTO_URI_PREFIX.size());
483     return tmp.substr(0, tmp.find_first_of('/'));
484 }
485 
GetTimeIdFromUri(const std::vector<std::string> & uriBatch,std::vector<std::string> & timeIdBatch)486 void MediaFileUri::GetTimeIdFromUri(const std::vector<std::string> &uriBatch, std::vector<std::string> &timeIdBatch)
487 {
488     for (size_t i = 0; i < uriBatch.size(); ++i) {
489         std::string uri = uriBatch.at(i);
490         if (uri.empty()) {
491             continue;
492         }
493         auto index = uri.rfind(ML_URI_TIME_ID);
494         if (index == std::string::npos) {
495             MEDIA_ERR_LOG("GetTimeIdFromUri find index for time_id failed: %{private}s", uri.c_str());
496             continue;
497         }
498         timeIdBatch.emplace_back(uri.substr(index + ML_URI_TIME_ID.length()));
499     }
500 }
501 
GetTimeIdFromUri(const std::vector<std::string> & uriBatch,std::vector<std::string> & timeIdBatch,int32_t & start,int32_t & count)502 void MediaFileUri::GetTimeIdFromUri(const std::vector<std::string> &uriBatch, std::vector<std::string> &timeIdBatch,
503     int32_t &start, int32_t &count)
504 {
505     if (uriBatch.size() != BATCH_SIZE_START_AND_END) {
506         return;
507     }
508     std::vector<int32_t> offset;
509     for (size_t i = 0; i < uriBatch.size(); ++i) {
510         std::string uri = uriBatch.at(i);
511         if (uri.empty()) {
512             continue;
513         }
514         auto indexStart = uri.rfind(ML_URI_TIME_ID);
515         if (indexStart == std::string::npos) {
516             MEDIA_ERR_LOG("GetTimeIdFromUri find indexStart for time_id failed: %{private}s", uri.c_str());
517             continue;
518         }
519         auto indexEnd = uri.rfind(ML_URI_OFFSET);
520         if (indexEnd == std::string::npos) {
521             MEDIA_ERR_LOG("GetTimeIdFromUri find indexEnd for time_id failed: %{private}s", uri.c_str());
522             continue;
523         }
524         uint32_t timeIdLen = indexEnd - indexStart - ML_URI_TIME_ID.length();
525         if (indexEnd <= uri.size()) {
526             timeIdBatch.emplace_back(uri.substr(indexStart + ML_URI_TIME_ID.length(), timeIdLen));
527         }
528         if (indexEnd + ML_URI_OFFSET.length() <= uri.size()) {
529             offset.emplace_back(stoi(uri.substr(indexEnd + ML_URI_OFFSET.length())));
530         }
531     }
532     if (offset.size() != BATCH_SIZE_START_AND_END) {
533         return;
534     }
535     start = offset[0];
536     count = offset[1] - offset[0] + 1;
537 }
538 
CreateAssetBucket(int32_t fileId,int32_t & bucketNum)539 int32_t MediaFileUri::CreateAssetBucket(int32_t fileId, int32_t &bucketNum)
540 {
541     if (fileId < 0) {
542         MEDIA_ERR_LOG("input fileId [%{public}d] is invalid", fileId);
543         return E_INVALID_FILEID;
544     }
545     fileId = fileId % ASSET_MAX_NUM;
546     int start = ASSET_DIR_START_NUM;
547     int divider = ASSET_DIR_START_NUM;
548     while (fileId > start * ASSET_IN_BUCKET_NUM_MAX) {
549         divider = start;
550         start *= 2; // 2: Left shift offset
551     }
552 
553     int fileIdRemainder = fileId % divider;
554     if (fileIdRemainder == 0) {
555         bucketNum = start + fileIdRemainder;
556     } else {
557         bucketNum = (start - divider) + fileIdRemainder;
558     }
559     return E_OK;
560 }
561 
GetPathFromUri(const string & uri,bool isPhoto)562 string MediaFileUri::GetPathFromUri(const string &uri, bool isPhoto)
563 {
564     size_t index = uri.rfind('/');
565     if (index == string::npos) {
566         MEDIA_ERR_LOG("index invalid %{private}s", uri.c_str());
567         return "";
568     }
569     string realTitle = uri.substr(0, index);
570     index = realTitle.rfind('/');
571     if (index == string::npos) {
572         MEDIA_ERR_LOG("invalid realTitle %{private}s", uri.c_str());
573         return "";
574     }
575     realTitle = realTitle.substr(index + 1);
576     index = realTitle.rfind('_');
577     if (index == string::npos) {
578         MEDIA_ERR_LOG("realTitle can not find _ %{private}s", uri.c_str());
579         return "";
580     }
581     string fileId = realTitle.substr(index + 1);
582     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
583         MEDIA_ERR_LOG("fileId invalid %{private}s", uri.c_str());
584         return "";
585     }
586     int32_t fileUniqueId = 0;
587     if (!StrToInt(fileId, fileUniqueId)) {
588         MEDIA_ERR_LOG("invalid fileuri %{private}s", uri.c_str());
589         return "";
590     }
591     int32_t bucketNum = 0;
592     CreateAssetBucket(fileUniqueId, bucketNum);
593 
594     string ext = MediaFileUtils::GetExtensionFromPath(uri);
595     if (ext.empty()) {
596         MEDIA_ERR_LOG("invalid ext %{private}s", uri.c_str());
597         return "";
598     }
599 
600     string path = ROOT_MEDIA_DIR;
601     if (isPhoto) {
602         path += PHOTO_BUCKET + "/" + to_string(bucketNum) + "/" + realTitle + "." + ext;
603     } else {
604         path += AUDIO_BUCKET + "/" + to_string(bucketNum) + "/" + realTitle + "." + ext;
605     }
606     if (!MediaFileUtils::IsFileExists(path)) {
607         MEDIA_ERR_LOG("file not exist, path=%{private}s", path.c_str());
608         return "";
609     }
610     return path;
611 }
612 
GetPhotoUri(const std::string & fileId,const std::string & path,const std::string & displayName)613 string MediaFileUri::GetPhotoUri(const std::string &fileId, const std::string &path, const std::string &displayName)
614 {
615     std::string uri = "";
616     CHECK_AND_RETURN_RET_LOG(!fileId.empty(), uri, "Failed to get fileId");
617     CHECK_AND_RETURN_RET_LOG(!path.empty(), uri, "Failed to get path");
618     CHECK_AND_RETURN_RET_LOG(!displayName.empty(), uri, "Failed to get displayName");
619 
620     std::string tmpStr;
621     size_t lastSlashPos = path.find_last_of('/');
622     if (lastSlashPos != std::string::npos) {
623         tmpStr = path.substr(lastSlashPos + 1);
624     } else {
625         tmpStr = path;
626     }
627 
628     std::string fileNameWithoutSuffix;
629     size_t lastDotPos = tmpStr.find_last_of('.');
630     if (lastDotPos!= std::string::npos) {
631         fileNameWithoutSuffix = tmpStr.substr(0, lastDotPos);
632     } else {
633         fileNameWithoutSuffix = tmpStr;
634     }
635 
636     uri = PhotoColumn::PHOTO_URI_PREFIX + fileId + "/" + fileNameWithoutSuffix + "/" +displayName;
637     return uri;
638 }
639 } // namespace Media
640 } // namespace OHOS
641