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